//高阶函数:变量可以指向函数，函数的参数能接受变量->函数的参数能接受函数，这种函数被称为高阶函数
//作为参数被传递的函数就是 回调函数
//一个最简单的高阶函数
function add(x, y, f) {
  return f(x) + f(y);
}

console.log(add(-5, 6, Math.abs));

//map和reduce函数 都是高阶函数 接受一个函数作为参数
//map和reduce函数都定义在js的Array中 将这些函数应用在Array中
("use strict");
function pow(x) {
  return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow);
debugger;
console.log(results);

//reduce 和序列下一个元素做累计计算
//reduce求和
var a = [1, 3, 5, 7, 9];
var result1 = a.reduce(function (x, y) {
  return x + y;
}); //定义了一个匿名函数
console.log(result1);
//reduce求累积

var arr = [2, 4, 6, 8];
function product(n) {
  function prox(x, y) {
    return x * y;
  }
  return n.reduce(prox);
}
console.log(product(arr));
//或者如下的写法
var arr1 = [2, 4, 6, 8];
function product1(n) {
  return n.reduce(function (x, y) {
    return x * y;
  });
}
console.log(product1(arr));

////////////////////////////////////////////////////////////////////////////////////////
//filter用于把Array的元素过滤掉，接受一个函数，根据结果是true还是false 决定保留还是丢弃该元素
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
  return x % 2 !== 0;
});
console.log(r);
//过滤空字符串
var arr = ["A", "", "B", null, undefined, "C", "   "];
var r = arr.filter(function (s) {
  return s && s.trim();
});
console.log(r);

//回调函数 可以有多个参数 通常只使用第一个参数，表示Array的某个元素 回调函数还可以接受另外两个参数
//表示元素的位置和数组本身
var arr = ["A", "B", "C"];
var r = arr.filter(function (element, index, self) {
  console.log(element); // 依次打印'A', 'B', 'C'
  console.log(index); // 依次打印0, 1, 2
  console.log(self); // self就是变量arr
  return true;
});

//利用filter去除Array重复元素
("use strict");
var r,
  arr = [
    "apple",
    "strawberry",
    "banana",
    "pear",
    "apple",
    "orange",
    "orange",
    "strawberry",
  ];
r = arr
  .filter(function (element, index, self) {
    return self.indexOf(element) === index;
  })
  [
    //indexOf总是返回第一个元素所在位置,后续重复元素的位置不相等被filter了

    //////////////////////////////////////////////////////////////////////////////////////////
    //sort排序算法 排序是比较两个元素的大小。但是碰到字符串或者两个对象，直接比较大小是没有意义的 需要把比较的过程抽象
    //成函数，出来 大于的为1 小于的为-1 等于的为0  sort()方法会直接对Array函数进行修改，返回的结果仍然是当前的Array
    ("Google", "Apple", "Microsoft")
  ].sort(); // ['Apple', 'Google', 'Microsoft'];
["Google", "apple", "Microsoft"].sort(); // ['Google', 'Microsoft", 'apple']
[10, 20, 1, 2].sort(); // [1, 10, 2, 20]
//sort默认是字符串 以ASCII码来排序 数字的话是会先转化为字符 然后再进行排序
//sort高阶函数，它可以接受一个比较函数 来自定义排序
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
  if (x < y) {
    return 1;
  }
  if (x > y) {
    return -1;
  }
  return 0;
}); // [20, 10, 2, 1]
//忽略大小写比较
var arr = ["Google", "apple", "Microsoft"];
arr.sort(function (s1, s2) {
  x1 = s1.toUpperCase();
  x2 = s2.toUpperCase();
  if (x1 < x2) {
    return -1;
  }
  if (x1 > x2) {
    return 1;
  }
  return 0;
}); // ['apple', 'Google', 'Microsoft']
///////////////////////////////////////////Array还提供了其他高阶函数 every() find() findindex() foreach()//////////////////////
//every()可以判断数组的所有元素是否满足测试条件
var arr = ["Apple", "pear", "orange"];
console.log(
  arr.every(function (s) {
    return s.toLowCase() === s;
  })
);
//find()用于查找复合条件的第一个元素，找到了返回这个元素，否则返回undefined
var arr = ["Apple", "pear", "orange"];
console.log(
  arr.find(function (s) {
    return s.toLowCase() === s;
  })
);
//findIndex()查找复合条件的第一个元素，返回这个元素的索引，没找到返回undefined
var arr = ["Apple", "pear", "orange"];
console.log(
  arr.findIndex(function (s) {
    return s.toLowerCase() === s;
  })
);
//forEach forEach()和map类似,但是不会返回新的数组 forEach常用于遍历数组，所以传入的函数不需要返回值
var arr = ["Apple", "pear", "orange"];
arr.forEach(console.log); // 依次打印每个元素
